package com.tonann.app.controller;

import com.tonann.app.domain.*;
import com.tonann.app.mqtt.dao.MQTTSensor;
import com.tonann.app.service.IAppDeviceService;
import com.tonann.app.service.IAppFaultRuleService;
import com.tonann.app.service.IAppSensorService;
import com.tonann.app.service.SseEmitterService;
import com.tonann.app.utils.NumberUtil;
import com.tonann.app.websocket.MsgType;
import com.tonann.app.websocket.SocketMsg;
import com.tonann.app.websocket.WebSocketServer;
import com.tonann.common.annotation.Log;
import com.tonann.common.core.controller.BaseController;
import com.tonann.common.core.domain.AjaxResult;
import com.tonann.common.core.domain.entity.SysDept;
import com.tonann.common.core.domain.entity.SysPlace;
import com.tonann.common.core.page.TableDataInfo;
import com.tonann.common.enums.BusinessType;
import com.tonann.common.utils.poi.ExcelUtil;
import com.tonann.system.service.ISysDeptService;
import com.tonann.system.service.ISysDictDataService;
import com.tonann.system.service.ISysPlaceService;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.slf4j.XSlf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 传感器管理Controller
 *
 * @author tonann
 * @date 2022-10-17
 */
@RestController
@RequestMapping("/app/sensor")
public class AppSensorController extends BaseController {
    @Autowired
    private IAppSensorService appSensorService;
    @Autowired
    private IAppDeviceService deviceService;
    @Autowired
    private IAppFaultRuleService faultRuleService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private ISysDictDataService dictDataService;
    @Autowired
    private ISysPlaceService placeService;
    @Autowired
    private SseEmitterService sseEmitterService;

    private Logger log = LoggerFactory.getLogger(AppSensorController.class);

    /**
     * 查询传感器管理列表
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:list')")
    @GetMapping("/list")
    public TableDataInfo list(AppSensor appSensor) {
        if (appSensor.getProjectId() != null && appSensor.getDeviceId() == null) {
            AppDevice device = new AppDevice();
            device.setProjectId(appSensor.getProjectId());
            List<AppDevice> deviceList = deviceService.selectAppDeviceAll(device);
            List<Long> deviceIdList = deviceList.stream().map(AppDevice::getDeviceId).collect(Collectors.toList());
            if (!deviceIdList.isEmpty()) {
                appSensor.setDeviceIds(deviceIdList.toArray(new Long[deviceIdList.size()]));
            }
        } else if (appSensor.getDeviceId() != null) {
            List<AppDevice> deviceList = deviceService.selectChildrenAppDeviceById(appSensor.getDeviceId());
            List<Long> deviceIdList = deviceList.stream().map(AppDevice::getDeviceId).collect(Collectors.toList());
            if (!deviceIdList.isEmpty()) {
                deviceIdList.add(appSensor.getDeviceId());
                appSensor.setDeviceIds(deviceIdList.toArray(new Long[deviceIdList.size()]));
                appSensor.setDeviceId(null);
            }
        }
        startPage();
        List<AppSensor> list = appSensorService.selectAppSensorList(appSensor);
        TableDataInfo tableDataInfo = getDataTable(list);
        tableDataInfo = appSensorService.selectValueFromRedis(tableDataInfo);
        List<AppSensor> sensorList = (List<AppSensor>) tableDataInfo.getRows();
        List<AppSensorData> sensorDataList = new ArrayList<>();
        for (AppSensor sensor : sensorList) {
            AppSensorData data = new AppSensorData();
            BeanUtils.copyProperties(sensor, data);
            data.setGatewayName(sensor.getDevice().getAppGateway().getGatewayName());
            data.setGatewayType(sensor.getDevice().getAppGateway().getGatewayType());
            data.setDeviceName(sensor.getDevice().getDeviceName());
            if (sensor.getFaultRule() != null) {
                data.setRuleName(sensor.getFaultRule().getRuleName());
            } else if (sensor.getFaultRuleId() != null) {
                AppFaultRule faultRule = faultRuleService.selectAppFaultRuleByFaultRuleId(sensor.getFaultRuleId());
                if (faultRule != null) {
                    data.setRuleName(faultRule.getRuleName());
                }
            }
            sensorDataList.add(data);
        }
        tableDataInfo.setRows(sensorDataList);
        return tableDataInfo;
    }

    /**
     * 查询传感器管理列表
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:list')")
    @GetMapping("/all")
    public AjaxResult listAll(AppSensor appSensor) {
        List<AppSensor> list = appSensorService.selectAppSensorNameAll(appSensor);
        return AjaxResult.success(list);
    }

    /**
     * 导出传感器管理列表
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:export')")
    @Log(title = "传感器管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, AppSensor appSensor) {
        List<AppSensor> list = appSensorService.selectAppSensorList(appSensor);
        List<AppDevice> deviceList = deviceService.selectAppDeviceAll(new AppDevice());
        Map<Long, String> deviceMap = deviceList.stream().collect(Collectors.toMap(AppDevice::getDeviceId, AppDevice::getDeviceName));
        List<AppFaultRule> faultRuleList = faultRuleService.selectAppFaultRuleList(new AppFaultRule());
        Map<Long, AppFaultRule> faultRuleMap = faultRuleList.stream().collect(Collectors.toMap(AppFaultRule::getFaultRuleId, item -> item));
        List<SysPlace> sysPlaceList = placeService.selectPlaceList(new SysPlace());
        Map<Long, SysPlace> sysPlaceMap = sysPlaceList.stream().collect(Collectors.toMap(SysPlace::getPlaceId, item -> item));
        List<SysDept> sysDeptList = deptService.selectDeptList(new SysDept());
        Map<Long, SysDept> sysDeptMap = sysDeptList.stream().collect(Collectors.toMap(SysDept::getDeptId, item -> item));
        List<Long> sensorIdList = list.stream().map(AppSensor::getSensorId).collect(Collectors.toList());
        List<AppSensorPlace> sensorPlaceIdList = appSensorService.selectAppSensorPlaceIdListBySensorIds(sensorIdList);
        List<AppSensorDept> sensorDeptIdList = appSensorService.selectAppSensorDeptIdListBySensorIds(sensorIdList);
        Map<Long, String> sensorPlaceName = new HashMap<>();
        Map<Long, String> sensorDeptName = new HashMap<>();
        for (AppSensorPlace place : sensorPlaceIdList) {
            SysPlace sysPlace = sysPlaceMap.get(place.getPlaceId());
            if (sysPlace != null) {
                String ancestors = sysPlace.getAncestors();
                String[] an = ancestors.split(",");
                StringBuilder placeName = new StringBuilder();
                for (String a : an) {
                    if (!StringUtils.isEmpty(a) && !a.trim().equals("0")) {
                        SysPlace parentPlace = sysPlaceMap.get(Long.valueOf(a));
                        if (parentPlace != null) {
                            placeName.append(parentPlace.getPlaceName());
                            placeName.append(":");
                        }
                    }
                }
                String name = placeName.toString();
                if (name.lastIndexOf(":") > -1) {
                    name = placeName.substring(0, placeName.lastIndexOf(":"));
                }
                if (!name.isEmpty()) {
                    sensorPlaceName.merge(place.getSensorId(), name, (a, b) -> a + "," + b);
                }
            }
        }
        for (AppSensorDept dept : sensorDeptIdList) {
            SysDept sysDept = sysDeptMap.get(dept.getDeptId());
            if (sysDept != null) {
                String ancestors = sysDept.getAncestors();
                String[] an = ancestors.split(",");
                StringBuilder deptName = new StringBuilder();
                for (String a : an) {
                    if (!StringUtils.isEmpty(a) && !a.trim().equals("0")) {
                        SysDept parentDept = sysDeptMap.get(Long.valueOf(a));
                        if (parentDept != null) {
                            deptName.append(parentDept.getDeptName());
                            deptName.append(":");
                        }
                    }
                }
                String name = deptName.toString();
                if (name.lastIndexOf(":") > -1) {
                    name = deptName.substring(0, deptName.lastIndexOf(":"));
                }
                if (!name.isEmpty()) {
                    sensorDeptName.merge(dept.getSensorId(), name, (a, b) -> a + "," + b);
                }
            }
        }

        List<AppSensorData> dataList = new ArrayList<>();
        for (AppSensor sensor : list) {
            AppSensorData data = new AppSensorData();
            data.setDeviceName(deviceMap.get(sensor.getDeviceId()));
            data.setMqttTopic(sensor.getMqttTopic());
            data.setMqttDeviceChannel(sensor.getMqttDeviceChannel());
            data.setMqttDeviceName(sensor.getMqttDeviceName());
            data.setMqttDeviceTag(sensor.getMqttDeviceTag());
            data.setMqttWriteTopic(sensor.getMqttWriteTopic());
            if (sensor.getFaultRuleId() != null && faultRuleMap.get(sensor.getFaultRuleId()) != null) {
                AppFaultRule rule = faultRuleMap.get(sensor.getFaultRuleId());
                data.setRuleName(rule.getRuleName());
                data.setAlarmBottom(rule.getRuleValueBottomlimit());
                data.setAlarmTop(rule.getRuleValueToplimit());
            }
            data.setSensorCode(sensor.getSensorCode());
            data.setSensorName(sensor.getSensorName());
            data.setSensorType(sensor.getSensorType());
            data.setOutputAddress(sensor.getOutputAddress());
            data.setInputAddress(sensor.getInputAddress());
            data.setUnit(sensor.getUnit());
            data.setDeptName(sensorDeptName.get(sensor.getSensorId()));
            data.setPlaceName(sensorPlaceName.get(sensor.getSensorId()));
            if (sensor.getIsDisplay() != null && sensor.getIsDisplay().equals("1")){
                data.setIsDisplay("是");
            }
            if (sensor.getIsLight() != null && sensor.getIsLight().equals("1")){
                data.setSpecialPurpose("灯光控制");
            }
            else if (sensor.getIsForce() != null && sensor.getIsForce().equals("1")){
                data.setSpecialPurpose("强制排风");
            }
            else if (sensor.getIsHeight() != null && sensor.getIsHeight().equals("1")){
                data.setSpecialPurpose("窗高控制");
            }
            else if (sensor.getIsOn() != null && sensor.getIsOn().equals("1")){
                data.setSpecialPurpose("电源开关");
            }
            else if (sensor.getIsBeing() != null && sensor.getIsBeing().equals("1")){
                data.setSpecialPurpose("有无人");
            }
            else if (sensor.getIsMute() != null && sensor.getIsMute().equals("1")){
                data.setSpecialPurpose("静音控制");
            }
            else if (sensor.getIsExhaust() != null && sensor.getIsExhaust().equals("1")){
                data.setSpecialPurpose("排风阀");
            }
            else if (sensor.getIsFresh() != null && sensor.getIsFresh().equals("1")){
                data.setSpecialPurpose("新风阀");
            }
            else if (sensor.getIsAutoDoor() != null && sensor.getIsAutoDoor().equals("1")){
                data.setSpecialPurpose("自动门");
            }
            else if (sensor.getWorkMode() != null && sensor.getWorkMode().equals("1")){
                data.setSpecialPurpose("工作模式");
            }
            dataList.add(data);
        }
        ExcelUtil<AppSensorData> util = new ExcelUtil<AppSensorData>(AppSensorData.class);
        util.exportExcel(response, dataList, "传感器管理数据");
    }

    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<AppSensorData> util = new ExcelUtil<AppSensorData>(AppSensorData.class);
        util.importTemplateExcel(response, "sheet1");
    }

    /**
     * 获取传感器管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:query')")
    @GetMapping(value = "/{sensorId}")
    public AjaxResult getInfo(@PathVariable("sensorId") Long sensorId) {
        return AjaxResult.success(appSensorService.selectAppSensorBySensorId(sensorId));
    }

    /**
     * 新增传感器管理
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:add')")
    @Log(title = "传感器管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody AppSensor appSensor) {
        appSensor.setCreateBy(getUsername());
        appSensor.setUpdateBy(getUsername());
        return toAjax(appSensorService.insertAppSensor(appSensor));
    }

    /**
     * 修改传感器管理
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:edit')")
    @Log(title = "传感器管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody AppSensor appSensor) {
        appSensor.setUpdateBy(getUsername());
        return toAjax(appSensorService.updateAppSensor(appSensor));
    }

    /**
     * 删除传感器管理
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:remove')")
    @Log(title = "传感器管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{sensorIds}")
    public AjaxResult remove(@PathVariable Long[] sensorIds) {
        return toAjax(appSensorService.deleteAppSensorBySensorIds(sensorIds));
    }

    /**
     * 删除所有传感器管理
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:remove')")
    @Log(title = "传感器管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/all")
    public AjaxResult removeAll() {
//        List<AppSensor> list = appSensorService.selectAppSensorAll(new AppSensor());
//        for(AppSensor sensor : list){
//            appSensorService.deleteAppSensorBySensorId(sensor.getSensorId());
//        }
        return AjaxResult.success();
    }

    @Log(title = "传感器管理", businessType = BusinessType.INSERT)
    @PreAuthorize("@ss.hasPermi('app:sensor:add')")
    @PostMapping(value = "/upload")
    public AjaxResult importExcelEmp(MultipartFile file, String sid) {
        try {
            ExcelUtil excelUtil = new ExcelUtil<>(AppSensor.class);
            List<AppSensor> sensorList = excelUtil.importExcel(file.getInputStream());
            String userName = getUsername();
            double verifyTime = sensorList.size() * 0.1;
            double addTime = sensorList.size() * 0.8;
            log.info("收到传感器数据导入，共{}条",sensorList.size());
            new Thread(() -> {
                try {
                    dealData(sensorList, userName, sid);
//                    demoData(sensorList, userName, sid);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
            Map<String, String> map = new HashMap<>();
            map.put("verifyTime", String.valueOf(verifyTime));
            map.put("addTime", String.valueOf(addTime));
            return AjaxResult.success(map);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("导入数据错误");
        }
    }

    protected void demoData(List<AppSensor> sensorList, String userName, String sid) throws InterruptedException {
        sseEmitterService.sendMessageToOneClient(sid, "服务器收到文件", MsgType.INFO);
        sendMsg("服务器收到文件", MsgType.INFO, sid);
        Thread.sleep(160000L);
        sseEmitterService.sendMessageToOneClient(sid, "数据准备完成", MsgType.INFO);
        sendMsg("数据准备完成", MsgType.INFO, sid);
        Thread.sleep(5000L);
        sseEmitterService.sendMessageToOneClient(sid, "验证通过，正在进行导入...", MsgType.INFO);
        sendMsg("验证通过，正在进行导入...", MsgType.INFO, sid);
        Thread.sleep(5000L);
        sseEmitterService.sendMessageToOneClient(sid, "表中传感器编号： 重复", MsgType.ERROR);
        sendMsg("表中传感器编号： 重复", MsgType.ERROR, sid);
//        sendMsg("导入成功", MsgType.INFO, sid);

    }

    private Map<String, List<AppDevice>> allDeviceNameMap;
    private Map<String, List<AppFaultRule>> allFaultRuleNameMap;
    private List<AppFaultRule> allFaultRuleList;
    private Map<String, List<SysPlace>> allPlaceNameMap;
    private Map<String, List<SysDept>> allDeptNameMap;

    protected void dealData(List<AppSensor> sensorList, String userName, String sid) throws InterruptedException {
        List<String> purposeList = new ArrayList<>();
        purposeList.add("灯光控制");
        purposeList.add("强制排风");
        purposeList.add("窗高控制");
        purposeList.add("电源开关");
        purposeList.add("有无人");
        purposeList.add("静音控制");
        purposeList.add("排风阀");
        purposeList.add("新风阀");
        purposeList.add("自动门");
        purposeList.add("工作模式");
        sendMsg("服务器收到文件", MsgType.INFO, sid);
        sseEmitterService.sendMessageToOneClient(sid, "服务器收到文件", MsgType.INFO);
        long start = System.currentTimeMillis();
        try {
            log.info("进入传感器数据准备");
            boolean isError = false;
            Map<String, List<AppSensor>> sensorCodeMap = sensorList.stream().collect(Collectors.groupingBy(AppSensor::getSensorCode));
            for (List<AppSensor> sensorDtoList : sensorCodeMap.values()) {
                if (sensorDtoList.size() > 1) {
                    sendMsg("表中传感器编号：" + sensorDtoList.get(0).getSensorCode() + "  重复", MsgType.ERROR, sid);
                    sseEmitterService.sendMessageToOneClient(sid, "表中传感器编号：" + sensorDtoList.get(0).getSensorCode() + "  重复", MsgType.ERROR);
                    log.info("表中传感器编号：" + sensorDtoList.get(0).getSensorCode() + "  重复");
                    isError = true;
                }
            }
            log.info("对传入的传感器编号合法性认证完成");
            Set<String> mqttSet = new HashSet<>();
            Set<String> mqttTagSet = MQTTSensor.getInstance().map.keySet();
            for (AppSensor sensor : sensorList) {
                if (sensor.getMqttDeviceChannel() != null && sensor.getMqttDeviceName() != null && sensor.getMqttDeviceTag() != null) {
                    String tag = sensor.getMqttDeviceChannel() + "." + sensor.getMqttDeviceName() + "." + sensor.getMqttDeviceTag();
                    if (mqttTagSet.contains(tag)) {
                        sendMsg("传感器：" + sensor.getSensorName() + "  的MQTT数据已经存在", MsgType.ERROR, sid);
                        sseEmitterService.sendMessageToOneClient(sid, "传感器：" + sensor.getSensorName() + "  的MQTT数据已经存在", MsgType.ERROR);
                        log.info("传感器：" + sensor.getSensorName() + "  的MQTT数据已经存在");
                        isError = true;
                    }
                    if (mqttSet.contains(tag)) {
                        sendMsg("表中传感器：" + sensor.getSensorName() + "  的MQTT数据重复", MsgType.ERROR, sid);
                        sseEmitterService.sendMessageToOneClient(sid, "表中传感器：" + sensor.getSensorName() + "  的MQTT数据重复", MsgType.ERROR);
                        log.info("表中传感器：" + sensor.getSensorName() + "  的MQTT数据重复");
                        isError = true;
                    } else {
                        mqttSet.add(tag);
                    }
                }
            }
            log.info("对传入的传感器MQTT信息合法性认证完成，是否有错误{}",isError);
            if (isError) {
                return;
            }
            this.prepareData(sensorList);
            log.info("数据准备完成");
            if ( allDeviceNameMap == null ||
                    allFaultRuleNameMap == null ||
                    allFaultRuleList == null ||
                    allPlaceNameMap == null ||
                    allDeptNameMap== null){
                sendMsg("数据准备失败", MsgType.ERROR, sid);
                sseEmitterService.sendMessageToOneClient(sid, "数据准备失败", MsgType.ERROR);
                log.info("数据准备失败");
                return;
            }
            log.info("数据准备耗时：{}", System.currentTimeMillis() - start);
            sendMsg("数据准备完成", MsgType.INFO, sid);
            sseEmitterService.sendMessageToOneClient(sid, "数据准备完成", MsgType.INFO);
            for (int i = 0; i < sensorList.size(); i++) {
                start = System.currentTimeMillis();
                AppSensor sensor = sensorList.get(i);
                if (sensor != null) {
                    String error = verifyExcelRowData(sensor, i + 1, allDeviceNameMap, allFaultRuleNameMap, null, purposeList);
                    if (error != null) {
                        sendMsg(error, MsgType.ERROR, sid);
                        sseEmitterService.sendMessageToOneClient(sid, error, MsgType.ERROR);
                        isError = true;
                        log.info(error);
                    }
                } else {
                    sendMsg("第" + (i + 2) + "行数据问题", MsgType.ERROR, sid);
                    sseEmitterService.sendMessageToOneClient(sid, "第" + (i + 2) + "行数据问题", MsgType.ERROR);
                    log.info("第" + (i + 2) + "行数据问题");
                    isError = true;
                }
                System.out.println("验证:" + (System.currentTimeMillis() - start));
            }
            log.info("对传入的传感器合法性认证完成，是否有错误{}",isError);
            if (isError) {
                return;
            }
            sendMsg("验证通过，正在进行导入...", MsgType.INFO, sid);
            sseEmitterService.sendMessageToOneClient(sid, "验证通过，正在进行导入...", MsgType.INFO);
            allFaultRuleList = faultRuleService.selectAppFaultRuleList(new AppFaultRule());
            allFaultRuleNameMap = allFaultRuleList.stream().collect(Collectors.groupingBy(AppFaultRule::getRuleName));
            for (AppSensor sensor : sensorList) {
                start = System.currentTimeMillis();
                insertData(sensor, userName, allDeviceNameMap, allFaultRuleNameMap, allPlaceNameMap, allDeptNameMap, purposeList);
                System.out.println("新增:" + (System.currentTimeMillis() - start));
            }
            log.info("对传入的导入成功完成");
        } catch (Exception e) {
            e.printStackTrace();
            sendMsg("新增数据异常", MsgType.ERROR, sid);
            sseEmitterService.sendMessageToOneClient(sid, "新增数据异常", MsgType.ERROR);
            return;
        }
        sendMsg("导入成功", MsgType.INFO, sid);
        sseEmitterService.sendMessageToOneClient(sid, "导入成功", MsgType.INFO);
    }

    private void prepareData(List<AppSensor> sensorList) {
        try {
//            List<AppDevice> allDeviceList = new ArrayList<>();
//            List<String> deviceNameList = sensorList.stream().map(AppSensor::getDeviceName).distinct().collect(Collectors.toList());
//            for (String deviceName : deviceNameList) {
//                List<AppDevice> appDeviceList = deviceService.selectAppDeviceByDeviceName(deviceName);
//                allDeviceList.addAll(appDeviceList);
//            }
//            List<String> faultRuleNameList = sensorList.stream().map(AppSensor::getRuleName).distinct().collect(Collectors.toList());
            List<AppDevice> allDeviceList = deviceService.selectAppDeviceAll(new AppDevice());
            log.info("所有设备查询完成");
            allDeviceNameMap = allDeviceList.stream().collect(Collectors.groupingBy(AppDevice::getDeviceName));
            log.info("按设备名称转换为Map完成");
            allFaultRuleList = faultRuleService.selectAppFaultRuleList(new AppFaultRule());
            log.info("所有告警规则完成");
//            List<AppFaultRule> allFaultRuleList = new ArrayList<>();
//            for (String ruleName : faultRuleNameList) {
//                List<AppFaultRule> ruleList = faultRuleService.selectAppFaultRuleByFaultRuleName(ruleName);
//                allFaultRuleList.addAll(ruleList);
//            }
            allFaultRuleNameMap = allFaultRuleList.stream().collect(Collectors.groupingBy(AppFaultRule::getRuleName));
            log.info("所有告警规则转换为Map完成");
//            List<AppSensor> allSensorList = appSensorService.selectAppSensorAll(new AppSensor());
//            List<String> sensorNameList = allSensorList.stream().map(AppSensor::getSensorName).collect(Collectors.toList());
            List<SysPlace> placeList = placeService.selectPlaceAll(new SysPlace());
            allPlaceNameMap = placeList.stream().collect(Collectors.groupingBy(SysPlace::getPlaceName));
            log.info("所有空间位置查询完成");
            List<SysDept> deptList = deptService.selectDeptAll(new SysDept());
            allDeptNameMap = deptList.stream().collect(Collectors.groupingBy(SysDept::getDeptName));
            log.info("所有部门查询完成");
        } catch (Exception e) {
            e.printStackTrace();
            this.prepareData(sensorList);
        }
    }

    /**
     * 通过实现handle方法编写我们要对每行数据的操作方式
     */
    private String verifyExcelRowData(AppSensor sensor, int rowIndex,
                                      Map<String, List<AppDevice>> allDeviceNameMap,
                                      Map<String, List<AppFaultRule>> allFaultRuleNameMap,
                                      List<String> sensorNameList,
                                      List<String> purposeList
    ) {
        String deviceName = sensor.getDeviceName();
        if (deviceName == null || deviceName.trim().isEmpty()) {
            return "第" + (++rowIndex) + "行,设备名称为空";
        }
        List<AppDevice> deviceList = allDeviceNameMap.get(deviceName);
        if (deviceList == null || deviceList.isEmpty()) {
            return "第" + (++rowIndex) + "行,设备不存在";
        } else if (deviceList.size() > 1) {
            return "第" + (++rowIndex) + "行,设备名称有多个";
        }
        AppDevice device = deviceList.get(0);
        AppGateway gateway = device.getAppGateway();
        if (gateway == null) {

            return "第" + (++rowIndex) + "行,网关不存在";
        }
        String gatewayType = device.getAppGateway().getGatewayType();
        if (gatewayType == null || !"1,2,3".contains(gatewayType)) {

            return "第" + (++rowIndex) + "行,网关类型不存在";
        }
        String mqttTopic = sensor.getMqttTopic();
        if ("2".contains(gatewayType) && mqttTopic == null) {

            return "第" + (++rowIndex) + "行,网关是MQTT必须填写MQTT的订阅主题";
        }
        String mqttWriteTopic = sensor.getMqttWriteTopic();
        String specialPurpose = sensor.getSpecialPurpose();
        if ("2".contains(gatewayType)) {
            if (specialPurpose != null && !specialPurpose.trim().isEmpty() && purposeList.contains(specialPurpose.trim())) {
                if (mqttTopic == null || mqttWriteTopic.trim().isEmpty()) {
                    return "第" + (++rowIndex) + "行,网关是MQTT且有特殊用途必须填写MQTT的写入主题";
                }
            }
        }
        String mqttDeviceChannel = sensor.getMqttDeviceChannel();
        if ("2".contains(gatewayType) && mqttDeviceChannel == null) {

            return "第" + (++rowIndex) + "行,网关是MQTT必须填写MQTT的设备通道";
        }

        String mqttDeviceName = sensor.getMqttDeviceName();
        if ("2".contains(gatewayType) && mqttDeviceName == null) {

            return "第" + (++rowIndex) + "行,网关是MQTT必须填写MQTT的设备名称";
        }

        String mqttDeviceTag = sensor.getMqttDeviceTag();
        if ("2".contains(gatewayType)) {
            if (mqttDeviceTag == null) {
                return "第" + (++rowIndex) + "行,网关是MQTT必须填写MQTT的标记";
            } else {
                String key = sensor.getMqttDeviceChannel() + "." + sensor.getMqttDeviceName() + "." + sensor.getMqttDeviceTag();
                if (MQTTSensor.getInstance().map.get(key) != null) {
                    return "第" + (++rowIndex) + "行,此条传感器MQTT的信息已经存在";
                }
            }
        }
        String faultName = sensor.getRuleName();
        if (faultName.trim().isEmpty()) {
            return "第" + (++rowIndex) + "行,告警规则未填写";
        }
        String alarmBottom = sensor.getAlarmBottom();
        String alarmTop = sensor.getAlarmTop();
        List<AppFaultRule> faultRuleList = allFaultRuleNameMap.get(faultName.trim());
        if (!faultName.trim().isEmpty() && (faultRuleList == null || faultRuleList.isEmpty())) {
            if (alarmBottom.trim().isEmpty()) {
                return "第" + (++rowIndex) + "行,告警规则需要新增，告警下限没有设置";
            }
            if (alarmTop.trim().isEmpty()) {
                return "第" + (++rowIndex) + "行,告警规则需要新增，告警上限没有设置";
            }
            if (!NumberUtil.isIntegerOrDecimal(alarmBottom)) {
                return "第" + (++rowIndex) + "行,告警规则需要新增，告警下限不是可用的数字";
            }
            if (!NumberUtil.isIntegerOrDecimal(alarmTop)) {
                return "第" + (++rowIndex) + "行,告警规则需要新增，告警上限不是可用的数字";
            }
            AppFaultRule faultRule = new AppFaultRule();
            faultRule.setRuleCode(UUID.randomUUID().toString().replaceAll("-", ""));
            faultRule.setRuleName(faultName);
            faultRule.setRuleDescribe(faultName);
            faultRule.setRuleValueBottomlimit(alarmBottom);
            faultRule.setRuleValueToplimit(alarmTop);
            faultRuleService.insertAppFaultRule(faultRule);
        }
        if (!faultName.trim().isEmpty() && faultRuleList != null && faultRuleList.size() > 1) {
            return "第" + (++rowIndex) + "行,告警规则存在多条数据";
        }
        String sensorCode = sensor.getSensorCode();
        if (sensorCode == null || sensorCode.trim().isEmpty()) {

            return "第" + (++rowIndex) + "行,传感器编号未填写";
        }
        String sensorName = sensor.getSensorName();
        if (sensorName == null || sensorName.trim().isEmpty()) {

            return "第" + (++rowIndex) + "行,传感器名称未填写";
        }
//        if (sensorNameList.contains(sensorName)) {
//            return "第" + (++rowIndex) + "行,传感器名称已存在";
//        }
        String sensorType = sensor.getSensorType();
        if (sensorType == null || sensorType.trim().isEmpty()) { // || dictDetail != null) {
            return "第" + (++rowIndex) + "行,传感器类型未填写或类型不存在";
        }
        String outputAddress = sensor.getOutputAddress();
        if ("1".contains(gatewayType) && (outputAddress == null || outputAddress.trim().isEmpty())) {

            return "第" + (++rowIndex) + "行,读取数值地址未填写";
        }
        if ("1".contains(gatewayType) && (Integer.parseInt(outputAddress) / 10000 != 4)) {

            return "第" + (++rowIndex) + "行,读取数值地址格式错误";
        }
        String inputAddress = sensor.getInputAddress();
        if ("PLC".contains(gatewayType) && (inputAddress != null && !inputAddress.trim().isEmpty() && Integer.parseInt(inputAddress) / 10000 != 4)) {

            return "第" + (++rowIndex) + "行,设置数值地址格式错误";
        }
//        Long magnification = sensor.getMagnification();
//        if (magnification == null || magnification == 0L) {
//            return "第" + (++rowIndex) + "行,放大倍数错误,不能为空或者0";
//        }
        String unit = sensor.getUnit();
        if (unit == null || unit.isEmpty()) {
            return "第" + (++rowIndex) + "行,计量单位未填写或单位不存在";
        }
//        Long intervalTime = sensor.getIntervalTime();
//        if (intervalTime == 0L) {
//
//            return "第" + (++rowIndex) + "行,取值周期错误";
//        }
//        String isDisplay = sensor.getIsDisplay();
//        if (isDisplay.isEmpty() || !"是否".contains(isDisplay)) {
//
//            return "第" + (++rowIndex) + "行,面板显示未填写";
//        }
//        String isEnergy = sensor.getIsEnergy();
//        if (isEnergy.isEmpty() || !"是否".contains(isEnergy)) {
//
//            return "第" + (++rowIndex) + "行,能耗计算未填写";
//        }
//        String isExhaust = sensor.getIsExhaust();
//        if (isExhaust.isEmpty() || !"是否".contains(isExhaust)) {
//
//            return "第" + (++rowIndex) + "行，是否排风未填写";
//        }
//        String isFresh = sensor.getIsFresh();
//        if (isFresh.isEmpty() || !"是否".contains(isFresh)) {
//
//            return "第" + (++rowIndex) + "行,是否新风未填写";
//        }
//        String isBeing = sensor.getIsBeing();
//        if (isBeing.isEmpty() || !"是否".contains(isBeing)) {
//
//            return "第" + (++rowIndex) + "行,是否是有无人未填写";
//        }
//        String isLight = sensor.getIsLight();
//        if (isLight.isEmpty() || !"是否".contains(isLight)) {
//
//            return "第" + (++rowIndex) + "行,是否是灯控未填写";
//        }
//        String isForce = sensor.getIsForce();
//        if (isForce.isEmpty() || !"是否".contains(isForce)) {
//
//            return "第" + (++rowIndex) + "行,是否是是否强制排风未填写";
//        }
//        String isWindow = sensor.getIsHeight();
//        if (isWindow.isEmpty() || !"是否".contains(isWindow)) {
//
//            return "第" + (++rowIndex) + "行,是否是窗高未填写";
//        }
//        String isPower = sensor.getIsOn();
//        if (isPower.isEmpty() || !"是否".contains(isPower)) {
//
//            return "第" + (++rowIndex) + "行,是否是电源控制未填写";
//        }
//        String isMute = sensor.getIsMute();
//        if (isMute.isEmpty() || !"是否".contains(isMute)) {
//
//            return "第" + (++rowIndex) + "行,是否是静音未填写";
//        }

//        String deptName = sensor.getDeptName();
//        List<String> deptNameList = new ArrayList<>();
//        if (deptName != null && deptName.contains(",")) {
//            String[] deptNames = deptName.split(",");
//            deptNameList = Arrays.asList(deptNames);
//        } else if (deptName != null && deptName.contains("，")) {
//            String[] deptNames = deptName.split("，");
//            deptNameList = Arrays.asList(deptNames);
//        }
//        if (!deptNameList.isEmpty()) {
//            List<Long> list = new ArrayList<>();
//            for (String name : deptNameList) {
//                List<SysDept> deptList = deptService.selectDeptByDeptName(name.trim());
//                if (deptList.size() == 1) {
//                    SysDept dept = deptList.get(0);
//                    list.add(dept.getDeptId());
//                }
//            }
//            sensor.setDeptIds(list.toArray(new Long[list.size()]));
//        }
//        String placeName = sensor.getPlaceName();
//        List<String> placeNameList = new ArrayList<>();
//        if (placeName != null && placeName.contains(",")) {
//            String[] placeNames = placeName.split(",");
//            placeNameList = Arrays.asList(placeNames);
//        } else if (placeName != null && placeName.contains("，")) {
//            String[] placeNames = placeName.split("，");
//            placeNameList = Arrays.asList(placeNames);
//        }
//        if (!placeNameList.isEmpty()) {
//            List<Long> list = new ArrayList<>();
//            for (String name : placeNameList) {
//                List<SysPlace> placeList = placeService.selectPlaceByPlaceName(name.trim());
//                if (placeList.size() == 1) {
//                    SysPlace place = placeList.get(0);
//                    list.add(place.getPlaceId());
//                }
//            }
//            sensor.setPlaceIds(list.toArray(new Long[0]));
//        }

//        String judgeStr = isExhaust + isFresh + isBeing + isLight + isForce + isWindow + isPower + isMute;
//        if (judgeStr.split("是").length > 1) {
//
//            return "第" + (++rowIndex) + "行,一个传感器只能有一个用途";
//        }
        return null;
    }

    private void sendMsg(String msg, MsgType msgType, String sid) {
        try {
            WebSocketServer.sendInfo(new SocketMsg(msg, msgType), sid);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    private void insertData(AppSensor sensor, String userName,
                            Map<String, List<AppDevice>> allDeviceNameMap,
                            Map<String, List<AppFaultRule>> allFaultNameMap,
                            Map<String, List<SysPlace>> allPlaceNameMap,
                            Map<String, List<SysDept>> allDeptNameMap,
                            List<String> purposeList
    ) {
        long start = System.currentTimeMillis();
        List<AppDevice> device = allDeviceNameMap.get(sensor.getDeviceName());
        if (device != null && !device.isEmpty()) {
            sensor.setDeviceId(device.get(0).getDeviceId());
        }
        List<AppFaultRule> faultRule = allFaultNameMap.get(sensor.getRuleName());
        if (faultRule != null && !faultRule.isEmpty()) {
            sensor.setFaultRuleId(faultRule.get(0).getFaultRuleId());
        }
        String isDisplay = sensor.getIsDisplay();
        if (isDisplay != null && isDisplay.trim().equals("是")) {
            sensor.setIsDisplay("1");
        } else {
            sensor.setIsDisplay("0");
        }
        sensor.setIsEnergy("0");
        sensor.setIsExhaust("0");
        sensor.setIsFresh("0");
        sensor.setIsBeing("0");
        sensor.setIsLight("0");
        sensor.setIsForce("0");
        sensor.setIsHeight("0");
        sensor.setIsOn("0");
        sensor.setIsMute("0");
        sensor.setIsAutoDoor("0");
        sensor.setWorkMode("0");
        String specialPurpose = sensor.getSpecialPurpose();
        if (specialPurpose != null && !specialPurpose.trim().isEmpty()) {
            int index = purposeList.indexOf(specialPurpose.trim());
            switch (index) {
                case 0:
                    sensor.setIsLight("1"); //灯光控制
                    break;
                case 1:
                    sensor.setIsForce("1"); //强制排风
                    break;
                case 2:
                    sensor.setIsHeight("1"); //窗高控制
                    break;
                case 3:
                    sensor.setIsOn("1"); //电源开关
                    break;
                case 4:
                    sensor.setIsBeing("1"); //有无人
                    break;
                case 5:
                    sensor.setIsMute("1"); //静音控制
                    break;
                case 6:
                    sensor.setIsExhaust("1"); //排风阀
                    break;
                case 7:
                    sensor.setIsFresh("1"); //新风阀
                    break;
                case 8:
                    sensor.setIsAutoDoor("1"); //自动门
                    break;
                case 9:
                    sensor.setWorkMode("1"); //工作模式
                    break;
                default:
                    break;
            }
        }
        sensor.setMagnification(1L);
//        String sensorType = sensor.getSensorType();
//        String dictDetail = dictDataService.selectDictValue("app_sensor_type", sensorType);
//        sensor.setSensorType(dictDetail);
        sensor.setCreateBy(userName);
        sensor.setUpdateBy(userName);
        sensor.setValue("0");
        System.out.println("数据构造时间:" + (System.currentTimeMillis() - start));
        start = System.currentTimeMillis();
        List<Long> deptIds = new ArrayList<>();
        String deptName = sensor.getDeptName();
        if (deptName != null && !deptName.trim().isEmpty()) {
            List<String> deptNames = getMultiName(deptName);
            for (String name : deptNames) {
                name = name.replaceAll(":", ":");
                name = name.replaceAll("：", ":");
                String[] names = name.split(":");
                SysDept parentDept = null;
                for (int i = 0; i < names.length; i++) {
                    String n = names[i];
                    if (n != null && !n.trim().isEmpty()) {
                        List<SysDept> deptList = allDeptNameMap.get(n.trim());
                        if (i == 0) {
                            List<SysDept> firstDeptList = deptList.stream().filter(item -> item.getParentId() == null || item.getParentId() == 0L).collect(Collectors.toList());
                            if (firstDeptList.isEmpty()) {
                                parentDept = new SysDept();
                                parentDept.setParentId(0L);
                                parentDept.setDeptName(n.trim());
                                parentDept.setAncestors("0");
                                parentDept.setStatus("0");
                                deptService.insertDept(parentDept);
                                if (parentDept.getDeptId() == null) ;
                                {
                                    parentDept.setAncestors(null);
                                    List<SysDept> sysDeptList = deptService.selectDeptAll(parentDept);
                                    if (!sysDeptList.isEmpty()) {
                                        parentDept = sysDeptList.get(0);
                                        List<SysDept> newDeptList = new ArrayList<>();
                                        newDeptList.add(parentDept);
                                        allDeptNameMap.put(n.trim(), newDeptList);
                                    }
                                }
                            } else if (firstDeptList.size() == 1) {
                                parentDept = firstDeptList.get(0);
                            }
                        } else if (parentDept != null) {
                            final Long parentId = parentDept.getDeptId();
                            if (parentId != null && deptList != null) {
                                List<SysDept> elseDeptList = deptList.stream().filter(item -> item.getParentId() != null && item.getParentId().equals(parentId)).collect(Collectors.toList());
                                if (elseDeptList.isEmpty()) {
                                    parentDept = new SysDept();
                                    parentDept.setParentId(parentId);
                                    parentDept.setDeptName(n.trim());
                                    parentDept.setStatus("0");
                                    deptService.insertDept(parentDept);
                                    if (parentDept.getDeptId() == null) ;
                                    {
                                        List<SysDept> sysDeptList = deptService.selectDeptAll(parentDept);
                                        if (!sysDeptList.isEmpty()) {
                                            parentDept = sysDeptList.get(0);
                                            List<SysDept> newDeptList = new ArrayList<>();
                                            newDeptList.add(parentDept);
                                            allDeptNameMap.put(n.trim(), newDeptList);
                                        }
                                    }
                                } else if (elseDeptList.size() == 1) {
                                    parentDept = elseDeptList.get(0);
                                }
                            } else if (parentId != null) {
                                parentDept = new SysDept();
                                parentDept.setParentId(parentId);
                                parentDept.setDeptName(n.trim());
                                parentDept.setStatus("0");
                                deptService.insertDept(parentDept);
                                if (parentDept.getDeptId() == null) ;
                                {
                                    List<SysDept> sysDeptList = deptService.selectDeptAll(parentDept);
                                    if (!sysDeptList.isEmpty()) {
                                        parentDept = sysDeptList.get(0);
                                        List<SysDept> newDeptList = new ArrayList<>();
                                        newDeptList.add(parentDept);
                                        allDeptNameMap.put(n.trim(), newDeptList);
                                    }
                                }
                            }
                        }
                        if (parentDept != null && parentDept.getDeptId() != null && i == names.length - 1) {
                            deptIds.add(parentDept.getDeptId());
                        }
                    }
                }
            }
        }
        sensor.setDeptIds(deptIds.toArray(new Long[0]));
        List<Long> placeIds = new ArrayList<>();
        String placeName = sensor.getPlaceName();
        if (placeName != null && !placeName.trim().isEmpty()) {
            List<String> placeNames = getMultiName(placeName);
            for (String name : placeNames) {
                name = name.replaceAll(":", ":");
                name = name.replaceAll("：", ":");
                String[] names = name.split(":");
                SysPlace parentPlace = null;
                for (int i = 0; i < names.length; i++) {
                    String n = names[i];
                    if (n != null && !n.trim().isEmpty()) {
                        List<SysPlace> placeList = allPlaceNameMap.get(n.trim());
                        if (i == 0) {
                            List<SysPlace> firstPlaceList = placeList.stream().filter(item -> item.getParentId() == null || item.getParentId() == 0L).collect(Collectors.toList());
                            if (firstPlaceList.isEmpty()) {
                                parentPlace = new SysPlace();
                                parentPlace.setParentId(0L);
                                parentPlace.setPlaceName(n.trim());
                                parentPlace.setAncestors("0");
                                parentPlace.setStatus("0");
                                placeService.insertPlace(parentPlace);
                                if (parentPlace.getParentId() == null) {
                                    parentPlace.setAncestors(null);
                                    List<SysPlace> sysPlaceList = placeService.selectPlaceAll(parentPlace);
                                    if (!sysPlaceList.isEmpty()) {
                                        parentPlace = sysPlaceList.get(0);
                                        List<SysPlace> newPlaceList = new ArrayList<>();
                                        newPlaceList.add(parentPlace);
                                        allPlaceNameMap.put(n.trim(), newPlaceList);
                                    }
                                }
                            } else if (firstPlaceList.size() == 1) {
                                parentPlace = firstPlaceList.get(0);
                            }
                        } else if (parentPlace != null) {
                            final Long parentId = parentPlace.getPlaceId();
                            if (parentId != null && placeList != null) {
                                List<SysPlace> elsePlaceList = placeList.stream().filter(item -> item.getParentId() != null && item.getParentId().equals(parentId)).collect(Collectors.toList());
                                if (elsePlaceList.isEmpty()) {
                                    parentPlace = new SysPlace();
                                    parentPlace.setParentId(parentId);
                                    parentPlace.setPlaceName(n.trim());
                                    parentPlace.setAncestors("0");
                                    parentPlace.setStatus("0");
                                    placeService.insertPlace(parentPlace);
                                    if (parentPlace.getPlaceId() == null) {
                                        List<SysPlace> sysPlaceList = placeService.selectPlaceAll(parentPlace);
                                        if (!sysPlaceList.isEmpty()) {
                                            parentPlace = sysPlaceList.get(0);
                                            List<SysPlace> newPlaceList = new ArrayList<>();
                                            newPlaceList.add(parentPlace);
                                            allPlaceNameMap.put(n.trim(), newPlaceList);
                                        }
                                    }
                                } else if (elsePlaceList.size() == 1) {
                                    parentPlace = elsePlaceList.get(0);
                                }
                            } else if (parentId != null) {
                                parentPlace = new SysPlace();
                                parentPlace.setParentId(parentId);
                                parentPlace.setPlaceName(n.trim());
                                parentPlace.setAncestors("0");
                                parentPlace.setStatus("0");
                                placeService.insertPlace(parentPlace);
                                if (parentPlace.getPlaceId() == null) {
                                    List<SysPlace> sysPlaceList = placeService.selectPlaceAll(parentPlace);
                                    if (!sysPlaceList.isEmpty()) {
                                        parentPlace = sysPlaceList.get(0);
                                        List<SysPlace> newPlaceList = new ArrayList<>();
                                        newPlaceList.add(parentPlace);
                                        allPlaceNameMap.put(n.trim(), newPlaceList);
                                    }
                                }
                            }
                        }
                        if (parentPlace != null && parentPlace.getPlaceId() != null && i == names.length - 1) {
                            placeIds.add(parentPlace.getPlaceId());
                        }
                    }
                }
            }
        }
        sensor.setPlaceIds(placeIds.toArray(new Long[0]));
        System.out.println("空间位置和部门处理时间:" + (System.currentTimeMillis() - start));
        start = System.currentTimeMillis();
        appSensorService.insertAppSensor(sensor);
        System.out.println("传感器新增时间:" + (System.currentTimeMillis() - start));
        start = System.currentTimeMillis();
        if (sensor.getSensorId() != null) {
            appSensorService.authDeptScope(sensor);
            appSensorService.authPlaceScope(sensor);
            System.out.println("空间位置和部门新增时间:" + (System.currentTimeMillis() - start));
        }
    }

    private List<String> getMultiName(String name) {
        name = name.replaceAll(",", ",");
        name = name.replaceAll("，", ",");
        return getSplit(name, ",");
    }

    private List<String> getSplit(String str, String split) {
        return Arrays.asList(str.split(split));
    }

    /**
     * 修改保存数据权限
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:edit')")
    @Log(title = "运行设备", businessType = BusinessType.UPDATE)
    @PutMapping("/deptScope")
    public AjaxResult dataScope(@RequestBody AppSensor sensor) {
        return toAjax(appSensorService.authDeptScope(sensor));
    }


    /**
     * 修改保存数据权限
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:edit')")
    @Log(title = "运行设备", businessType = BusinessType.UPDATE)
    @PutMapping("/placeScope")
    public AjaxResult placeScope(@RequestBody AppSensor sensor) {
        return toAjax(appSensorService.authPlaceScope(sensor));
    }

    /**
     * 获取对应角色设备树列表
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:query')")
    @GetMapping(value = "/deptTree/{sensorId}")
    public AjaxResult deptTree(@PathVariable("sensorId") Long sensorId) {
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", appSensorService.selectAppSensorDeptListBySensorId(sensorId));
        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
        return ajax;
    }

    /**
     * 获取对应角色空间位置树列表
     */
    @PreAuthorize("@ss.hasPermi('app:sensor:query')")
    @GetMapping(value = "/placeTree/{sensorId}")
    public AjaxResult placeTree(@PathVariable("sensorId") Long sensorId) {
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", appSensorService.selectAppSensorPlaceListBySensorId(sensorId));
        ajax.put("places", placeService.selectPlaceTreeList(new SysPlace()));
        return ajax;
    }
}
